package leetcode101.dynamic_planning;

import java.util.LinkedList;
import java.util.Queue;

/**
 * @author Synhard
 * @version 1.0
 * @Class Code5
 * @Description 542. 01 矩阵
 * 给定一个由 0 和 1 组成的矩阵，找出每个元素到最近的 0 的距离。
 *
 * 两个相邻元素间的距离为 1 。
 * 示例 1：
 *
 * 输入：
 * [[0,0,0],
 *  [0,1,0],
 *  [0,0,0]]
 *
 * 输出：
 * [[0,0,0],
 *  [0,1,0],
 *  [0,0,0]]
 * 示例 2：
 *
 * 输入：
 * [[0,0,0],
 *  [0,1,0],
 *  [1,1,1]]
 *
 * 输出：
 * [[0,0,0],
 *  [0,1,0],
 *  [1,2,1]]
 *  
 *
 * 提示：
 *
 * 给定矩阵的元素个数不超过 10000。
 * 给定矩阵中至少有一个元素是 0。
 * 矩阵中的元素只在四个方向上相邻: 上、下、左、右。
 * @tel 13001321080
 * @email 823436512@qq.com
 * @date 2021-04-12 9:22
 */
public class Code5 {

    public static int[] directions = new int[]{-1, 0, 1, 0, -1};

    public static void main(String[] args) {
        int[][] matrix = new int[][] {{0, 0, 0}, {0, 1, 0}, {0, 0, 0}};
        updateMatrix(matrix);
    }

    public static int[][] updateMatrix(int[][] matrix) {
        /*
        声明一个check数组，一个queue队列辅助bfs，声明dp数组作为结果
         */
        int m = matrix.length;
        int n = matrix[0].length;
        int[][] check = new int[m][n], dp = new int[m][n];
        Queue<int[]> queue = new LinkedList<>();
        int step = 0;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    queue.add(new int[]{i, j});
                    check[i][j] = 1;
                }
            }
        }

        while (!queue.isEmpty()) {
            step++;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int[] head = queue.poll();
                for (int j = 0; j < directions.length - 1; j++) {
                    int x = head[0] + directions[j];
                    int y = head[1] + directions[j + 1];
                    if (x > -1 && x < m && y > -1 && y < n && check[x][y] == 0) {
                        check[x][y] = 1;
                        dp[x][y] = step;
                        queue.add(new int[]{x, y});
                    }
                }
            }
        }

        return dp;
    }
}
